﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Runtime.Serialization;
using System.Collections.Concurrent;

namespace InternalConferenceManagementSystem
{
    public class NamespaceConstants
    {
        public const string InternalConferenceManagementServiceNamespace = "http://RockBus.Samples.TeleConferencing/IInternalConferenceManagementService";
    }

    [DataContract(Namespace = NamespaceConstants.InternalConferenceManagementServiceNamespace)]
    public enum ConferenceStatusEnum
    {
        [EnumMember]
        Created,
        [EnumMember]
        Terminated,
    }

    [DataContract(Namespace = NamespaceConstants.InternalConferenceManagementServiceNamespace)]
    public class CreateConferenceRequest
    {
        [DataMember]
        public string ConferenceId { get; set; }

        [DataMember]
        public string UserId { get; set; }
    }

    [DataContract(Namespace = NamespaceConstants.InternalConferenceManagementServiceNamespace)]
    public class TerminateConferenceRequest
    {
        [DataMember]
        public string ConferenceId { get; set; }

        [DataMember]
        public string UserId { get; set; }
    }

    [DataContract(Namespace = NamespaceConstants.InternalConferenceManagementServiceNamespace)]
    public class ConferenceInfo
    {
        public ConferenceInfo()
        {
        }

        public ConferenceInfo(string conferenceId, string hostUserId)
        {
            this.ConferenceId = conferenceId;
            this.HostUserId = hostUserId;
            this.ConferenceStatus = ConferenceStatusEnum.Created;
            this.Timestamp = DateTime.UtcNow;
        }

        [DataMember]
        public string ConferenceId { get; set; }

        [DataMember]
        public string HostUserId { get; set; }

        [DataMember]
        public ConferenceStatusEnum ConferenceStatus { get; set; }

        [DataMember]
        public DateTime Timestamp { get; set; }

        public override string ToString()
        {
            return string.Format("ConferenceId: {0}; ConferenceStatus: {1}; HostUserId: {2}; Timestamp: {3}",
                this.ConferenceId,
                this.ConferenceStatus.ToString(),
                this.HostUserId,
                this.Timestamp);
        }
    }

    [DataContract(Namespace = NamespaceConstants.InternalConferenceManagementServiceNamespace)]
    public class GetConferenceStatusRequest
    {
        [DataMember]
        public string ConferenceId { get; set; }
    }

    [ServiceContract(Namespace = NamespaceConstants.InternalConferenceManagementServiceNamespace)]
    public interface IInternalConferenceManagementService
    {
        [OperationContract]
        ConferenceInfo CreateConference(CreateConferenceRequest request);

        [OperationContract]
        ConferenceInfo TerminateConference(TerminateConferenceRequest request);

        [OperationContract]
        ConferenceInfo GetConferenceStatus(GetConferenceStatusRequest request);
    }

    public class InternalConferenceManagementService : IInternalConferenceManagementService
    {
        public static ConcurrentDictionary<string, ConferenceInfo> Conferences = new ConcurrentDictionary<string, ConferenceInfo>();

        public ConferenceInfo CreateConference(CreateConferenceRequest request)
        {
            var ci = new ConferenceInfo(request.ConferenceId, request.UserId);
            Conferences.TryAdd(ci.ConferenceId, ci);

            ci = Conferences[ci.ConferenceId];
            Console.WriteLine("Conference created: {0}", ci.ToString());
            return ci;
        }

        public ConferenceInfo TerminateConference(TerminateConferenceRequest request)
        {
            ConferenceInfo ci = null;
            if (Conferences.TryRemove(request.ConferenceId, out ci))
            {
                ci.ConferenceStatus = ConferenceStatusEnum.Terminated;
                ci.Timestamp = DateTime.UtcNow;
            }
            else
            {
                ci = new ConferenceInfo(request.ConferenceId, request.UserId);
                ci.ConferenceStatus = ConferenceStatusEnum.Terminated;
            }

            Console.WriteLine("Conference terminated: {0}", ci.ToString());
            return ci;
        }

        public ConferenceInfo GetConferenceStatus(GetConferenceStatusRequest request)
        {
            var ci = Conferences[request.ConferenceId];
            return ci;
        }
    }
}
